package cmd

import (
	"github.com/carapace-sh/carapace"
	"github.com/carapace-sh/carapace-bin/pkg/actions/net"
	"github.com/carapace-sh/carapace-bin/pkg/actions/net/ssh"
	"github.com/carapace-sh/carapace-bin/pkg/actions/ps"
	"github.com/carapace-sh/carapace-bin/pkg/actions/tools/npm"
	"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
	Use:   "node",
	Short: "server-side JavaScript runtime",
	Long:  "https://nodejs.org/en/",
	Run:   func(cmd *cobra.Command, args []string) {},
}

func Execute() error {
	return rootCmd.Execute()
}
func init() {
	carapace.Gen(rootCmd).Standalone()

	rootCmd.Flags().Bool("abort-on-uncaught-exception", false, "aborting instead of exiting causes a core file to be generated for analysis")
	rootCmd.Flags().Bool("allow-addons", false, "allow use of addons when any permissions are set")
	rootCmd.Flags().Bool("allow-child-process", false, "allow use of child process when any permissions are set")
	rootCmd.Flags().String("allow-fs-read", "", "allow permissions to read the filesystem")
	rootCmd.Flags().String("allow-fs-write", "", "allow permissions to write in the filesystem")
	rootCmd.Flags().Bool("allow-wasi", false, "allow wasi when any permissions are set")
	rootCmd.Flags().Bool("allow-worker", false, "allow worker threads when any permissions are set")
	rootCmd.Flags().Bool("build-snapshot", false, "Generate a snapshot blob when the process exits")
	rootCmd.Flags().BoolP("check", "c", false, "syntax check script without executing")
	rootCmd.Flags().Bool("completion-bash", false, "print source-able bash completion script")
	rootCmd.Flags().StringP("conditions", "C", "", "additional user conditions for conditional exports and imports")
	rootCmd.Flags().Bool("cpu-prof", false, "Start the V8 CPU profiler on start up")
	rootCmd.Flags().String("cpu-prof-dir", "", "Directory where the V8 profiles generated by --cpu-prof will be placed")
	rootCmd.Flags().String("cpu-prof-interval", "", "specified sampling interval in microseconds for the V8 CPU profile")
	rootCmd.Flags().String("cpu-prof-name", "", "specified file name of the V8 CPU profile generated with --cpu-prof")
	rootCmd.Flags().Bool("debug-port", false, "set host:port for inspector")
	rootCmd.Flags().String("diagnostic-dir", "", "set dir for all output files")
	rootCmd.Flags().String("disable-proto", "", "disable Object.prototype.__proto__")
	rootCmd.Flags().Bool("disable-sigusr1", false, "Disable inspector thread to be listening for SIGUSR1 signal")
	rootCmd.Flags().String("disable-warning", "", "silence specific process warnings")
	rootCmd.Flags().Bool("disallow-code-generation-from-strings", false, "disallow eval and friends")
	rootCmd.Flags().String("dns-result-order", "", "set default value of verbatim in dns.lookup")
	rootCmd.Flags().Bool("enable-etw-stack-walking", false, "provides heap data to ETW Windows native tracing")
	rootCmd.Flags().Bool("enable-fips", false, "enable FIPS crypto at startup")
	rootCmd.Flags().Bool("enable-network-family-autoselection", false, "Enable network address family autodetection algorithm")
	rootCmd.Flags().Bool("enable-source-maps", false, "Source Map V3 support for stack traces")
	rootCmd.Flags().Bool("entry-url", false, "Treat the entrypoint as a URL")
	rootCmd.Flags().String("env-file", "", "set environment variables from supplied file")
	rootCmd.Flags().String("env-file-if-exists", "", "set environment variables from supplied file")
	rootCmd.Flags().StringP("eval", "e", "", "evaluate script")
	rootCmd.Flags().Bool("experimental-addon-modules", false, "experimental import support for addons")
	rootCmd.Flags().String("experimental-config-file", "", "set config file from supplied file")
	rootCmd.Flags().Bool("experimental-default-config-file", false, "set config file from default config file")
	rootCmd.Flags().Bool("experimental-eventsource", false, "experimental EventSource API")
	rootCmd.Flags().Bool("experimental-import-meta-resolve", false, "experimental ES Module import.meta.resolve() parentURL support")
	rootCmd.Flags().Bool("experimental-inspector-network-resource", false, "experimental load network resources via the inspector")
	rootCmd.Flags().Bool("experimental-network-inspection", false, "experimental network inspection support")
	rootCmd.Flags().Bool("experimental-print-required-tla", false, "Print pending top-level await")
	rootCmd.Flags().String("experimental-sea-config", "", "Generate a blob that can be embedded into the single executable application")
	rootCmd.Flags().Bool("experimental-test-coverage", false, "enable code coverage in the test runner")
	rootCmd.Flags().Bool("experimental-test-isolation", false, "configures the type of test isolation used in the test runner")
	rootCmd.Flags().Bool("experimental-test-module-mocks", false, "enable module mocking in the test runner")
	rootCmd.Flags().Bool("experimental-transform-types", false, "enable transformation of TypeScript-onlysyntax into JavaScript code")
	rootCmd.Flags().Bool("experimental-vm-modules", false, "experimental ES Module support in vm module")
	rootCmd.Flags().Bool("experimental-webstorage", false, "experimental Web Storage API")
	rootCmd.Flags().Bool("experimental-worker-inspection", false, "experimental worker inspection support")
	rootCmd.Flags().Bool("expose-gc", false, "expose gc extension")
	rootCmd.Flags().Bool("force-context-aware", false, "disable loading non-context-aware addons")
	rootCmd.Flags().Bool("force-fips", false, "force FIPS crypto (cannot be disabled)")
	rootCmd.Flags().Bool("force-node-api-uncaught-exceptions-policy", false, "enforces 'uncaughtException' event on Node API asynchronous callbacks")
	rootCmd.Flags().Bool("frozen-intrinsics", false, "experimental frozen intrinsics support")
	rootCmd.Flags().Bool("heap-prof", false, "Start the V8 heap profiler on start up, and write the heap profile to disk before exit")
	rootCmd.Flags().String("heap-prof-dir", "", "Directory where the V8 heap profiles generated by --heap-prof will be placed")
	rootCmd.Flags().String("heap-prof-interval", "", "specified sampling interval in bytes for the V8 heap profile generated")
	rootCmd.Flags().String("heap-prof-name", "", "specified file name of the V8 heap profile generated with --heap-prof")
	rootCmd.Flags().String("heapsnapshot-near-heap-limit", "", "Generate heap snapshots whenever V8 is approaching the heap limit")
	rootCmd.Flags().String("heapsnapshot-signal", "", "Generate heap snapshot on specified signal")
	rootCmd.Flags().BoolP("help", "h", false, "print node command line options")
	rootCmd.Flags().String("icu-data-dir", "", "set ICU data load path to dir")
	rootCmd.Flags().String("import", "", "ES module to preload")
	rootCmd.Flags().String("input-type", "", "set module type for string input")
	rootCmd.Flags().Bool("insecure-http-parser", false, "use an insecure HTTP parser that accepts invalid HTTP headers")
	rootCmd.Flags().String("inspect", "", "activate inspector on host:port")
	rootCmd.Flags().String("inspect-port", "", "set host:port for inspector")
	rootCmd.Flags().String("inspect-publish-uid", "", "comma separated list of destinations for inspector")
	rootCmd.Flags().String("inspect-wait", "", "activate inspector on host:port and wait for debugger to be attached")
	rootCmd.Flags().BoolP("interactive", "i", false, "always enter the REPL even if stdin does not appear to be a terminal")
	rootCmd.Flags().Bool("interpreted-frames-native-stack", false, "help system profilers to translate JavaScript interpreted frames")
	rootCmd.Flags().Bool("jitless", false, "disable runtime allocation of executable memory")
	rootCmd.Flags().String("loader", "", "use the specified module as a custom loader")
	rootCmd.Flags().String("localstorage-file", "", "file used to persist localStorage data")
	rootCmd.Flags().String("max-http-header-size", "", "set the maximum size of HTTP headers")
	rootCmd.Flags().String("max-old-space-size-percentage", "", "set V8's max old space size as a percentage of available memory")
	rootCmd.Flags().String("network-family-autoselection-attempt-timeout", "", "Sets the default value for the network family autoselection attempt timeout")
	rootCmd.Flags().Bool("no-addons", false, "disable loading native addons")
	rootCmd.Flags().Bool("no-async-context-frame", false, "Improve AsyncLocalStorage performance with AsyncContextFrame")
	rootCmd.Flags().Bool("no-deprecation", false, "silence deprecation warnings")
	rootCmd.Flags().Bool("no-experimental-detect-module", false, "when ambiguous modules fail to evaluate because they contain ES module syntax, try again to evaluate them as ES modules")
	rootCmd.Flags().Bool("no-experimental-global-navigator", false, "expose experimental Navigator API on the global scope")
	rootCmd.Flags().Bool("no-experimental-repl-await", false, "experimental await keyword support in REPL")
	rootCmd.Flags().Bool("no-experimental-require-module", false, "Allow loading synchronous ES Modules in require()")
	rootCmd.Flags().Bool("no-experimental-sqlite", false, "experimental node:sqlite module")
	rootCmd.Flags().Bool("no-experimental-strip-types", false, "Experimental type-stripping for TypeScript files")
	rootCmd.Flags().Bool("no-extra-info-on-fatal-exception", false, "hide extra information on fatal exception that causes exit")
	rootCmd.Flags().Bool("no-force-async-hooks-checks", false, "disable checks for async_hooks")
	rootCmd.Flags().Bool("no-global-search-paths", false, "disable global module search paths")
	rootCmd.Flags().Bool("no-network-family-autoselection", false, "Disable network address family autodetection algorithm")
	rootCmd.Flags().Bool("no-warnings", false, "silence all process warnings")
	rootCmd.Flags().Bool("node-memory-debug", false, "Run with extra debug checks for memory leaks in Node.js itself")
	rootCmd.Flags().String("openssl-config", "", "load OpenSSL configuration from the specified file")
	rootCmd.Flags().Bool("openssl-legacy-provider", false, "enable OpenSSL 3.0 legacy provider")
	rootCmd.Flags().Bool("openssl-shared-config", false, "enable OpenSSL shared configuration")
	rootCmd.Flags().Bool("pending-deprecation", false, "emit pending deprecation warnings")
	rootCmd.Flags().Bool("permission", false, "enable the permission system")
	rootCmd.Flags().Bool("preserve-symlinks", false, "preserve symbolic links when resolving")
	rootCmd.Flags().Bool("preserve-symlinks-main", false, "preserve symbolic links when resolving the main module")
	rootCmd.Flags().StringP("print", "p", "", "evaluate script and print result")
	rootCmd.Flags().Bool("prof", false, "Generate V8 profiler output")
	rootCmd.Flags().Bool("prof-process", false, "process V8 profiler output generated using --prof")
	rootCmd.Flags().String("redirect-warnings", "", "write warnings to file instead of stderr")
	rootCmd.Flags().Bool("report-compact", false, "output compact single-line JSON")
	rootCmd.Flags().String("report-dir", "", "define custom report pathname")
	rootCmd.Flags().String("report-directory", "", "define custom report pathname")
	rootCmd.Flags().Bool("report-exclude-env", false, "Exclude environment variables when generating report")
	rootCmd.Flags().Bool("report-exclude-network", false, "exclude network interface diagnostics")
	rootCmd.Flags().String("report-filename", "", "define custom report file name")
	rootCmd.Flags().Bool("report-on-fatalerror", false, "generate diagnostic report on fatal (internal) errors")
	rootCmd.Flags().Bool("report-on-signal", false, "generate diagnostic report upon receiving signals")
	rootCmd.Flags().String("report-signal", "", "causes diagnostic report to be produced on provided signal")
	rootCmd.Flags().Bool("report-uncaught-exception", false, "generate diagnostic report on uncaught exceptions")
	rootCmd.Flags().StringP("require", "r", "", "CommonJS module to preload")
	rootCmd.Flags().String("run", "", "Run a script specified in package.json")
	rootCmd.Flags().String("secure-heap", "", "total size of the OpenSSL secure heap")
	rootCmd.Flags().String("secure-heap-min", "", "minimum allocation size from the OpenSSL secure heap")
	rootCmd.Flags().String("snapshot-blob", "", "Path to the snapshot blob that's either the result of snapshotbuilding")
	rootCmd.Flags().Bool("test", false, "launch test runner on startup")
	rootCmd.Flags().String("test-concurrency", "", "specify test runner concurrency")
	rootCmd.Flags().String("test-coverage-branches", "", "the branch coverage minimum threshold")
	rootCmd.Flags().String("test-coverage-exclude", "", "exclude files from coverage report that match this glob pattern")
	rootCmd.Flags().String("test-coverage-functions", "", "the function coverage minimum threshold")
	rootCmd.Flags().String("test-coverage-include", "", "include files in coverage report that match this glob pattern")
	rootCmd.Flags().String("test-coverage-lines", "", "the line coverage minimum threshold")
	rootCmd.Flags().Bool("test-force-exit", false, "force test runner to exit upon completion")
	rootCmd.Flags().String("test-global-setup", "", "specifies the path to the global setup file")
	rootCmd.Flags().String("test-isolation", "", "configures the type of test isolation used in the test runner")
	rootCmd.Flags().String("test-name-pattern", "", "run tests whose name matches this regular expression")
	rootCmd.Flags().Bool("test-only", false, "run tests with 'only' option set")
	rootCmd.Flags().String("test-reporter", "", "report test output using the given reporter")
	rootCmd.Flags().String("test-reporter-destination", "", "report given reporter to the given destination")
	rootCmd.Flags().String("test-rerun-failures", "", "specifies the path to the rerun state file")
	rootCmd.Flags().String("test-shard", "", "run test at specific shard")
	rootCmd.Flags().String("test-skip-pattern", "", "run tests whose name do not match this regular expression")
	rootCmd.Flags().String("test-timeout", "", "specify test runner timeout")
	rootCmd.Flags().Bool("test-update-snapshots", false, "regenerate test snapshots")
	rootCmd.Flags().Bool("throw-deprecation", false, "throw an exception on deprecations")
	rootCmd.Flags().String("title", "", "the process title to use on startup")
	rootCmd.Flags().String("tls-cipher-list", "", "use an alternative default TLS cipher list")
	rootCmd.Flags().String("tls-keylog", "", "log TLS decryption keys to named file for traffic analysis")
	rootCmd.Flags().Bool("tls-max-v1.2", false, "set default TLS maximum to TLSv1.2")
	rootCmd.Flags().Bool("tls-max-v1.3", false, "set default TLS maximum to TLSv1.3")
	rootCmd.Flags().Bool("tls-min-v1.0", false, "set default TLS minimum to TLSv1.0")
	rootCmd.Flags().Bool("tls-min-v1.1", false, "set default TLS minimum to TLSv1.1")
	rootCmd.Flags().Bool("tls-min-v1.2", false, "set default TLS minimum to TLSv1.2")
	rootCmd.Flags().Bool("tls-min-v1.3", false, "set default TLS minimum to TLSv1.3")
	rootCmd.Flags().Bool("trace-deprecation", false, "show stack traces on deprecations")
	rootCmd.Flags().Bool("trace-env", false, "Print accesses to the environment variables")
	rootCmd.Flags().Bool("trace-env-js-stack", false, "Print accesses to the environment variables and the JavaScript stack trace")
	rootCmd.Flags().Bool("trace-env-native-stack", false, "Print accesses to the environment variables and the native stack trace")
	rootCmd.Flags().String("trace-event-categories", "", "comma separated list of trace event categories to record")
	rootCmd.Flags().String("trace-event-file-pattern", "", "Template string specifying the filepath for the trace-events data")
	rootCmd.Flags().Bool("trace-exit", false, "show stack trace when an environment exits")
	rootCmd.Flags().Bool("trace-promises", false, "show stack traces on promise initialization and resolution")
	rootCmd.Flags().String("trace-require-module", "", "Print access to require(esm)")
	rootCmd.Flags().Bool("trace-sigint", false, "enable printing JavaScript stacktrace on SIGINT")
	rootCmd.Flags().Bool("trace-sync-io", false, "show stack trace when use of sync IO is detected after the first tick")
	rootCmd.Flags().Bool("trace-tls", false, "prints TLS packet trace information to stderr")
	rootCmd.Flags().Bool("trace-uncaught", false, "show stack traces for the `throw` behind uncaught exceptions")
	rootCmd.Flags().Bool("trace-warnings", false, "show stack traces on process warnings")
	rootCmd.Flags().Bool("track-heap-objects", false, "track heap object allocations for heap snapshots")
	rootCmd.Flags().String("unhandled-rejections", "", "define unhandled rejections behavior")
	rootCmd.Flags().Bool("use-bundled-ca", false, "use bundled CA store (default)")
	rootCmd.Flags().Bool("use-env-proxy", false, "parse proxy settings from HTTP_PROXY/HTTPS_PROXY/NO_PROXYenvironment variables")
	rootCmd.Flags().String("use-largepages", "", "Map the Node.js static code to large pages")
	rootCmd.Flags().Bool("use-openssl-ca", false, "use OpenSSL's default CA store")
	rootCmd.Flags().Bool("use-system-ca", false, "use system's CA store")
	rootCmd.Flags().Bool("v8-options", false, "print V8 command line options")
	rootCmd.Flags().String("v8-pool-size", "", "set V8's thread pool size")
	rootCmd.Flags().BoolP("version", "v", false, "print Node.js version")
	rootCmd.Flags().Bool("watch", false, "run in watch mode")
	rootCmd.Flags().String("watch-kill-signal", "", "kill signal to send to the process on watch mode restarts")
	rootCmd.Flags().String("watch-path", "", "path to watch")
	rootCmd.Flags().Bool("watch-preserve-output", false, "preserve outputs on watch mode restart")
	rootCmd.Flags().Bool("zero-fill-buffers", false, "automatically zero-fill all newly allocated Buffer and SlowBuffer instances")

	carapace.Gen(rootCmd).FlagCompletion(carapace.ActionMap{
		"cpu-prof-dir":   carapace.ActionDirectories(),
		"diagnostic-dir": carapace.ActionDirectories(),
		"disable-proto":  carapace.ActionValues("delete", "throw"),
		"dns-result-order": carapace.ActionValuesDescribed(
			"ipv4first", "IPv4 addresses are placed before IPv6 addresses",
			"ipv6first", "IPv6 addresses are placed before IPv4 addresses",
			"verbatim", "addresses are in the order the DNS resolver returned",
		),
		"env-file":                 carapace.ActionFiles(),
		"env-file-if-exists":       carapace.ActionFiles(),
		"experimental-config-file": carapace.ActionFiles(),
		"heap-prof-dir":            carapace.ActionDirectories(),
		"heapsnapshot-signal":      ps.ActionKillSignals(),
		"icu-data-dir":             carapace.ActionDirectories(),
		"inspect-port":             net.ActionPorts(),
		"inspect-publish-uid":      carapace.ActionValues("http", "stderr").UniqueList(","),
		"localstorage-file":        carapace.ActionFiles(),
		"openssl-config":           carapace.ActionFiles(),
		"redirect-warnings":        carapace.ActionFiles(),
		"report-dir":               carapace.ActionDirectories(),
		"report-directory":         carapace.ActionDirectories(),
		"report-signal":            ps.ActionKillSignals(),
		"run":                      npm.ActionScripts(),
		"test-rerun-failures":      carapace.ActionFiles(),
		"tls-cipher-list":          ssh.ActionCiphers().UniqueList(":"),
		"tls-keylog":               carapace.ActionFiles(),
		"unhandled-rejections":     carapace.ActionValues("strict", "warn", "none"),
		"use-largepages":           carapace.ActionValues("off", "on", "silent"),
		"watch-kill-signal":        ps.ActionKillSignals(),
		"watch-path":               carapace.ActionDirectories(),
	})

	carapace.Gen(rootCmd).PositionalCompletion(
		carapace.ActionCallback(func(c carapace.Context) carapace.Action {
			return carapace.ActionFiles().Invoke(c).Merge(carapace.ActionValues("inspect").Invoke(c)).ToA()
		}),
		carapace.ActionCallback(func(c carapace.Context) carapace.Action {
			if c.Args[0] == "inspect" {
				return carapace.ActionFiles()
			} else {
				return carapace.ActionValues()
			}
		}),
	)
}
